package com.uyayo.oms.system.controller;

import com.uyayo.framework.common.annotation.MethodName;
import com.uyayo.framework.common.exception.CodeMultipleException;
import com.uyayo.framework.common.exception.ParentNotFoundException;
import com.uyayo.framework.message.model.Result;
import com.uyayo.framework.message.model.Tree;
import com.uyayo.framework.common.util.CodeUtil;
import com.uyayo.oms.system.biz.ParamBiz;
import com.uyayo.oms.system.vo.SysResourceVO;
import com.uyayo.system.authority.entity.SysResource;
import com.uyayo.system.authority.entity.SysUser;
import com.uyayo.system.authority.model.SysResourceCondition;
import com.uyayo.system.authority.service.SysResourceService;
import com.uyayo.system.authority.service.SysRoleService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.validation.Errors;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 
 * Title: ResourceController
 * Description:资源的Controller
 *
 * @author 乐乐科技.胡逢君
 * @date 2015-4-13下午4:03:35
 * @version 1.0
 */
@Controller
@RequestMapping("/system/authority/resource")
public class SysResourceController {

	private final Logger logger = LoggerFactory.getLogger(this.getClass());

	private final SysResourceService resourceService;

	private final ParamBiz paramBiz;

	private  final  MessageSource messageSource;

	private final SysRoleService roleService;

	@Autowired
	public SysResourceController(SysResourceService resourceService, ParamBiz paramBiz, MessageSource messageSource, SysRoleService roleService) {
		this.resourceService = resourceService;
		this.paramBiz = paramBiz;
		this.messageSource = messageSource;
		this.roleService = roleService;
	}

	/**
	 * 获得主菜单tree，也用于获得上级资源菜单combotree
	 */
	@ResponseBody
	@RequiresAuthentication
	@RequestMapping(value="/getMainMenu",method=RequestMethod.GET)
	public List<Tree> getMainMenu(@RequestParam(value = "parentId", required = false) String parentId) throws Exception{
		Subject subject = SecurityUtils.getSubject();
		SysUser sysUser = (SysUser) subject.getPrincipal();
		List<Tree> trees = new ArrayList<>();
		if(!subject.isAuthenticated()){
			return trees;
		}
		List<SysResource> sysResources = new ArrayList<>();

		SysResourceCondition sysResourceCondition = new SysResourceCondition();
		sysResourceCondition.setUserId(sysUser.getId());
		sysResourceCondition.setParentId(parentId);
		sysResourceCondition.setType(1);
		sysResourceCondition.setStatus(1);
		sysResources = resourceService.selectSysResourceByUserId(sysResourceCondition);

		trees = sysResources.stream().map(sysResource->{
			Tree node = new Tree();
			node.setId(sysResource.getId());
			node.setPid(sysResource.getParentId());
			node.setIconCls(sysResource.getIconCls());
			node.setName(sysResource.getName());
			Map<String, String> attributes = new HashMap<>();
			attributes.put("url", sysResource.getUrl());
			attributes.put("target", sysResource.getTarget());
			node.setState(sysResource.getExpandState());
			node.setAttributes(attributes);
			return node;
		}).collect(Collectors.toList());

		return trees;
	}


	/**
	 * 获得主菜单tree，也用于获得上级资源菜单combotree
	 */
	@ResponseBody
	@RequestMapping(value="/getSysResource",method=RequestMethod.GET)
	public List<Tree> getSysResource(@RequestParam(value = "parentId", required = false) String parentId) {
		Subject subject = SecurityUtils.getSubject();
		List<SysResource> sysResources;
		List<Tree> trees = new ArrayList<>();
		if(!subject.isAuthenticated()){
			return trees;
		}
		SysUser sysUser = (SysUser) subject.getPrincipal();

		try {
			SysResourceCondition sysResourceCondition = new SysResourceCondition();
			sysResourceCondition.setUserId(sysUser.getId());
			sysResourceCondition.setParentId(parentId);
			sysResourceCondition.setStatus(1);
			sysResources = resourceService.selectSysResourceByUserId(sysResourceCondition);
			if(sysUser.getId().equals("0")){
				sysResources = resourceService.selectResourceAll(new SysResource());
			}
			trees = sysResources.stream().map(sysResource->{
				Tree node = new Tree();
				node.setId(sysResource.getId());
				node.setPid(sysResource.getParentId());
				node.setIconCls(sysResource.getIconCls());
				node.setName(sysResource.getName());
				Map<String, String> attributes = new HashMap<>();
				attributes.put("url", sysResource.getUrl());
				attributes.put("target", sysResource.getTarget());
				node.setState(sysResource.getExpandState());
				node.setAttributes(attributes);
				return node;
			}).collect(Collectors.toList());

		} catch (Exception e) {
			e.printStackTrace();
		}

		return trees;
	}

	/**
	 * 获得资源treeGrid
	 */
	@ResponseBody
	@RequestMapping("treeGrid")
	@MethodName(value="系统管理->权限管理->资源管理->查询资源",type=2)
	public List<SysResource> treeGrid(SysResource resource) {
        return resourceService.resourceTreeGrid(resource);
	}


	/**
	 * 获得资源treeGrid
	 */
	@RequestMapping("index")
	@MethodName(value="系统管理->权限管理->资源管理")
	public ModelAndView index(ModelAndView modelAndView,String parentId) {
		modelAndView.addObject("parentId",parentId);
		modelAndView.setViewName(paramBiz.getManagerTemplatesPrefix()+"system/authority/resource/index");
		return modelAndView;
	}


	/**
	 * 查看资源信息
	 */
	@RequestMapping("view")
	public ModelAndView view(ModelAndView modelAndView,String id) {
		SysResource sysResource = new SysResource();
		try {
			sysResource = resourceService.selectResourceById(id);
		} catch (Exception e) {
			e.printStackTrace();
		}
		modelAndView.addObject("sysResource",sysResource);
		modelAndView.setViewName(paramBiz.getManagerTemplatesPrefix()+"system/authority/resource/view");
		return modelAndView;
	}

	/**
	 * 添加资源信息
	 */
	@RequestMapping(value = "add", method = RequestMethod.GET)
	public ModelAndView add(ModelAndView modelAndView) {
		modelAndView.setViewName(paramBiz.getManagerTemplatesPrefix()+"system/authority/resource/add");
		return modelAndView;
	}
	
	/**
	 * 保存一个资源
	 */
	@ResponseBody
	@RequestMapping(value = "add", method = RequestMethod.POST)
	@MethodName(value="系统管理->权限管理->资源管理->添加资源",type=2)
	public Result add(@Validated SysResourceVO sysResourceVO , Errors errors, HttpServletRequest request) {
		try {
			if (errors.hasErrors()) {
				return Result.errorAndMsg(errors.getFieldError().getDefaultMessage());
			}

			Subject subject = SecurityUtils.getSubject();
			SysUser sysUser = (SysUser) subject.getPrincipal();
			String id = CodeUtil.getTimeSequenceAsRandomCode();
			SysResource sysResource = new SysResource();
			sysResource.setId(id);
			sysResource.setCode(sysResourceVO.getCode());
			sysResource.setName(sysResourceVO.getName());
			sysResource.setParentId(sysResourceVO.getParentId());
			sysResource.setPermission(sysResourceVO.getPermission());
			sysResource.setIconCls(sysResourceVO.getIconCls());
			sysResource.setUrl(sysResourceVO.getUrl());
			sysResource.setType(sysResourceVO.getType());
			sysResource.setSortOrder(sysResourceVO.getSortOrder());
			sysResource.setHasChildren(false);
			sysResource.setDescription(sysResourceVO.getDescription());
			sysResource.setCreateBy(sysUser.getLoginname());
			sysResource.setCreateTime(new Date());
			sysResource.setRemark(sysResourceVO.getRemark());
			sysResource.setStatus(sysResourceVO.getStatus());
			resourceService.saveResource(sysResource);
		} catch (ParentNotFoundException e){
            String message = messageSource.getMessage("parent.not.found.error",new Object[]{}, request.getLocale());
            logger.error(message,e.getMessage());
            return Result.build(500,message);
        } catch (CodeMultipleException e){
            String message = messageSource.getMessage("code.multiple.error",new Object[]{}, request.getLocale());
            logger.error(message,e.getMessage());
            return Result.build(500,message);
        }catch(Exception e) {
            String message = messageSource.getMessage("server.error.500",new Object[]{}, request.getLocale());
            logger.error(message,e);
            return Result.error(500,message);
        }
        String message = messageSource.getMessage("save.success",new Object[]{}, request.getLocale());

        return Result.successAndMsg(message);
	}

	@ResponseBody
	@RequestMapping(value = "update", method = RequestMethod.GET)
	public ModelAndView getResourceById(ModelAndView modelAndView,String id) {
		SysResource resource = resourceService.selectResourceById(id);
		modelAndView.addObject("sysResource",resource);
		modelAndView.setViewName(paramBiz.getManagerTemplatesPrefix()+"system/authority/resource/update");
		return modelAndView;
	}

	/**
	 * 更新资源
	 */
	@ResponseBody
	@RequestMapping(value = "update", method = RequestMethod.POST)
	@MethodName(value="系统管理->权限管理->资源管理->修改资源",type=2)
	public Result updateResource(@Validated SysResourceVO sysResourceVO , Errors errors, HttpServletRequest request) {
		try {
			if (errors.hasErrors()) {
				return Result.errorAndMsg(errors.getFieldError().getDefaultMessage());
			}
			if (StringUtils.isEmpty(sysResourceVO.getId())) {
                String message = messageSource.getMessage("parameter.error",new Object[]{}, request.getLocale());
                logger.error(message);
                return Result.build(400,message);
            }

			if (sysResourceVO.getParentId() != null && Objects.equals(sysResourceVO.getId(), sysResourceVO.getParentId())) {
                String message = messageSource.getMessage("parent.self.error",new Object[]{}, request.getLocale());
                logger.error(message);
                return Result.build(400,message);
			}

			Subject subject = SecurityUtils.getSubject();
			SysUser sysUser = (SysUser) subject.getPrincipal();

			SysResource sysResource = new SysResource();

			sysResource.setId(sysResourceVO.getId());
			sysResource.setCode(sysResourceVO.getCode());
			sysResource.setName(sysResourceVO.getName());
			sysResource.setParentId(sysResourceVO.getParentId());
			sysResource.setPermission(sysResourceVO.getPermission());
			sysResource.setIconCls(sysResourceVO.getIconCls());
			sysResource.setUrl(sysResourceVO.getUrl());
			sysResource.setType(sysResourceVO.getType());
			sysResource.setSortOrder(sysResourceVO.getSortOrder());
			sysResource.setDescription(sysResourceVO.getDescription());
			sysResource.setUpdateBy(sysUser.getLoginname());
			sysResource.setUpdateTime(new Date());
			sysResource.setRemark(sysResourceVO.getRemark());
			sysResource.setStatus(sysResourceVO.getStatus());
			int updateCount = resourceService.updateResource(sysResource);
			if(updateCount<=0){
                String message = messageSource.getMessage("save.fail",new Object[]{}, request.getLocale());
                logger.info(message);
                return Result.build(400,message);
			}
            String message = messageSource.getMessage("save.success",new Object[]{}, request.getLocale());

            return Result.success(200,message);

		} catch (ParentNotFoundException e){
            String message = messageSource.getMessage("parent.not.found.error",new Object[]{}, request.getLocale());
            logger.info(message,e.getMessage());
			return Result.build(400,message);
		} catch (CodeMultipleException e){
            String message = messageSource.getMessage("code.multiple.error",new Object[]{}, request.getLocale());
            logger.info(message,e.getMessage());
			return Result.build(400,message);
		} catch(Exception e) {
		    String message = messageSource.getMessage("server.error.500",new Object[]{}, request.getLocale());
			logger.error(message,e);
			return Result.build(500,message);
		}
	}

    /**
     *删除资源
     * @param id 资源id
     * @param request HttpServletRequest
     * @return Result
     */
	@ResponseBody
	@RequestMapping(value="delete",method = RequestMethod.DELETE)
	@MethodName(value="系统管理->权限管理->资源管理->删除资源",type=2)
	public Result deleteResource(String id, HttpServletRequest request){

        try {
            if (StringUtils.isEmpty(id)) {
                String message = messageSource.getMessage("parameter.error",new Object[]{}, request.getLocale());
                logger.error(message);
                return Result.build(400,message);
            }
            int deleteCount = resourceService.deleteResource(id);
            if(deleteCount<=0){
                String message = messageSource.getMessage("delete.fail",new Object[]{}, request.getLocale());
                logger.error(message);
                return Result.build(400,message);
            }
        } catch(Exception e) {
            String message = messageSource.getMessage("server.error.500",new Object[]{}, request.getLocale());
            logger.error(message,e);
            return Result.build(500,message);
        }
        String message = messageSource.getMessage("delete.success",new Object[]{}, request.getLocale());
        logger.error(message);
        return Result.build(200,message);
	}
	
	/**
	 * 获得主菜单tree，也用于获得上级资源菜单combotree
	 */
	@ResponseBody
	@RequestMapping("comboTree")
	public List<Tree> comboTree(SysResource resource) {
		List<SysResource> menus = resourceService.selectResourceAll(resource);
		List<Tree> tree = new ArrayList<>();
		for (SysResource menu : menus) {
			Tree node = new Tree();
			node.setId(menu.getId());
			node.setPid(menu.getParentId());
			node.setIconCls(menu.getIconCls());
			node.setName(menu.getName());
			Map<String, String> attributes = new HashMap<>();
			attributes.put("url", menu.getUrl());
			attributes.put("target", menu.getTarget());
			node.setAttributes(attributes);
			tree.add(node);
			
		}
		return tree;
	}
	
	
}
